﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NP.BPMReportPlatform.Common
{
    /// <summary>
    /// 树构造器
    /// </summary>
    public static class TreeBuildTool
    {
        /// <summary>
        /// 递归工具类，用于遍历有父子关系的节点，例如菜单树，字典树等等
        /// </summary>
        /// <typeparam name="T">实体</typeparam>
        public class TreeBuild<T>
            where T : ITreeNode
        {
            /// <summary>
            /// 顶级节点的父节点Id(默认为空)
            /// </summary>
            private string rootParentId = string.Empty;

            /// <summary>
            /// 设置根节点方法
            /// 查询数据可以设置其他节点为根节点，避免父节点永远是0，查询不到数据的问题
            /// </summary>
            /// <param name="rootParentId">节点</param>
            public void SetRootParentId(string rootParentId)
            {
                this.rootParentId = rootParentId;
            }

            /// <summary>
            /// 构造树节点
            /// </summary>
            /// <param name="nodes">节点</param>
            /// <param name="rootParentId">设置根节点</param>
            /// <returns>节点信息</returns>
            public List<T> Build(List<T> nodes, string rootParentId = "")
            {
                this.SetRootParentId(rootParentId);
                var result = nodes.Where(t => (t.GetPid() ?? string.Empty) == rootParentId).ToList();
                result?.ForEach(u => this.BuildChildNodes(nodes, u));
                return result;
            }

            /// <summary>
            /// 构造子节点集合
            /// </summary>
            /// <param name="totalNodes">全部节点</param>
            /// <param name="node">节点</param>
            private void BuildChildNodes(List<T> totalNodes, T node)
            {
                var nodeSubList = totalNodes.Where(t => t.GetPid() == node.GetId()).ToList();

                nodeSubList.ForEach(u => this.BuildChildNodes(totalNodes, u));
                node.SetChildren(nodeSubList);
            }
        }
    }
    public interface ITreeNode
    {
        /// <summary>
        /// 获取节点id
        /// </summary>
        /// <returns>节点ID</returns>
        string GetId();

        /// <summary>
        /// 获取节点父id
        /// </summary>
        /// <returns>父亲</returns>
        string GetPid();

        /// <summary>
        /// 设置Children
        /// </summary>
        /// <param name="children">二子</param>
        void SetChildren(IList children);
    }
}
